package com.notice.config;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.log.LogFactory;
import com.hqjl.cache.KeyObj;
import com.notice.entity.LogDingInfo;
import com.notice.entity.LogDingProperties;
import com.notice.entity.ModeEnum;
import com.notice.message.At;
import com.notice.rule.LogNoticeRuleFactory;
import com.notice.rule.limit.DistributedLimit;
import com.notice.rule.limit.IRateLimit;
import com.notice.rule.limit.StandAloneLimit;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeansException;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import java.net.InetAddress;

/**
 * 处理中心
 *
 * @Author dzl
 * @Date 2022/1/4 3:25 下午
 */
@Slf4j
@Component
public class LogSpringContent implements ApplicationContextAware, CommandLineRunner {

    private static boolean noStartSuccess = true;

    private static LogDingInfo logDingInfo = null;

    private static ApplicationContext applicationContext;

    private static IRateLimit rateLimit;

    @Override
    public void setApplicationContext(@NonNull ApplicationContext applicationContext) throws BeansException {
        LogSpringContent.applicationContext = applicationContext;
    }

    @Override
    public void run(String... args) throws Exception {
        noStartSuccess = false;
        initProperties();
        initLimit();
        log.info("钉钉报警服务启动完成");
    }

    /**
     * 初始化限流器
     */
    private void initLimit() {
        final String mode = logDingInfo.getMode();
        if (ModeEnum.STAND_ALONE.name().equals(mode)) {
            rateLimit = new StandAloneLimit();
        } else if (ModeEnum.DISTRIBUTED.name().equals(mode)) {
            KeyObj keyObj = new KeyObj(IRateLimit.class.getSimpleName(), logDingInfo.getSecret(), logDingInfo.getProjectName(), logDingInfo.getProjectName());
            rateLimit = new DistributedLimit(keyObj.generateKey());
        } else {
            throw new LogNoticeException("限流模式无法识别ding-ding.logback.mode=".concat(mode));
        }
    }

    /**
     * 初始化信息加载
     */
    private void initProperties() {
        /*相关信息初始化*/
        LogDingProperties logDingProperties = applicationContext.getBean(LogDingProperties.class);
        checkProperties(logDingProperties);
        logDingProperties.setProjectName(StrUtil.isBlank(logDingProperties.getProjectName()) ? "未知" : logDingProperties.getProjectName());
        logDingInfo = new LogDingInfo();
        BeanUtils.copyProperties(logDingProperties, logDingInfo);
        logDingInfo.setPhonesList(StrUtil.isBlank(logDingInfo.getPhones()) ? null : StrUtil.split(logDingInfo.getPhones(), ",", true, true));
        /*1、项目ip初始化*/
        String hostAddress = "未知";
        try {
            hostAddress = InetAddress.getLocalHost().getHostAddress();
        } catch (Exception e) {
            LogFactory.get().warn(e, "ip无法确定");
        }
        logDingInfo.setHostAddress(hostAddress);

        /*2、打印头不变信息构建*/
        String sb = "主机地址：" +
                logDingInfo.getHostAddress() + "\n" +
                "项目名称：" +
                logDingInfo.getProjectName() + "\n";
        logDingInfo.setFinalHeaderMsg(sb);

        /*3、@的对象*/
        At at = new At();
        if (CollUtil.isEmpty(logDingInfo.getPhonesList())) {
            /*通知所有人*/
            at.setAtAll(true);
        } else {
            at.setAtMobiles(logDingInfo.getPhonesList());
        }
        logDingInfo.setAt(at);
        /*4、初始化过滤器*/
        LogNoticeRuleFactory.getLogErrorNoticeRule();
    }

    /**
     * 配置检查
     *
     * @param logDingProperties 配置类
     */
    private void checkProperties(LogDingProperties logDingProperties) {
        if (StrUtil.isBlank(logDingProperties.getSecret())) {
            throw new LogNoticeException("加签不可以为空ding-ding.logback.secret");
        }
        if (StrUtil.isBlank(logDingProperties.getWebHook())) {
            throw new LogNoticeException("回调地址不可以为空ding-ding.logback.web-hook");
        }
    }

    public static boolean isNoStartSuccess() {
        return noStartSuccess;
    }

    public static LogDingInfo getLogDingInfo() {
        return logDingInfo;
    }

    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    public static IRateLimit getRateLimit() {
        return rateLimit;
    }
}
